/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package clasificador.genetico.reglas;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import utils.Weighted;
import clasificador.ClasificadorEntrenado;
import clasificador.genetico.FitnessFunction;
import clasificador.genetico.HandOfGod;
import clasificador.genetico.PoliticaCruce;
import clasificador.genetico.PoliticaEmparejamiento;
import clasificador.genetico.PoliticaEmparejamientoAleatoria;
import clasificador.genetico.PoliticaMezcla;
import clasificador.genetico.PoliticaMutacion;
import clasificador.genetico.PoliticaSeleccion;
import clasificador.genetico.PoliticaSeleccionConstante;
import datos.Atributo;
import datos.AtributoFinito;
import datos.Dato;
import datos.DefinicionAtributosErroneaException;
import datos.MuestraClasificada;

/**
 *
 * @author Simply
 */
public class EvolveReglas2<Clase> extends ClasificadorEntrenado<Clase> {

    private double probCruce;
    private double decayCruce;
    private double propTest;
    private double probMutacion;
    private double nReglasMedio;
    private double sizePenalty;
    private int tamanoElite;
    private int tamanoPoblacion;
    private int nEpocas;
    private InterpretacionGenotipo<Clase> interpretacion;
    List<Clase> valores;
    private TGenotipo reglaFinal;
    private RuleSetFitness<Clase> fitness;

    public EvolveReglas2(MuestraClasificada<Clase> datosEntrenamiento,
            Map<String, Object> parametros) {
        super(datosEntrenamiento, parametros);
    }

    @Override
    public Clase clasificar(Dato d)
            throws DefinicionAtributosErroneaException {
        return interpretacion.clasificar(reglaFinal, interpretacion.normalizarAtributos(d));
    }

    @Override
    protected void entrenar(MuestraClasificada<Clase> datosEntrenamiento) {
        List<AtributoFinito> atributos = new ArrayList<>();
        for (Atributo a : datosEntrenamiento.getAtributos()) {
            if (a != datosEntrenamiento.getClase()) {
                atributos.add((AtributoFinito) a);
            }
        }
        this.interpretacion = new InterpretacionGenotipo<>(atributos, (AtributoFinito) datosEntrenamiento.getClase());
        this.valores = ((AtributoFinito) datosEntrenamiento.getClase()).getRango();

        PoliticaCruce<TGenotipo> cruce = new CruceReglas3(probCruce, decayCruce);
        PoliticaEmparejamiento<TGenotipo> emparejamiento = new PoliticaEmparejamientoAleatoria<>();
        PoliticaMezcla<TGenotipo> mezcla = new PoliticaMezcla<>(emparejamiento, cruce);

        FitnessFunction<TGenotipo> f = new RuleSetFitness2<>(datosEntrenamiento, sizePenalty, propTest);
        GeneradorReglas<Clase> generador = new GeneradorReglas<>(datosEntrenamiento, nReglasMedio);
        PoliticaMutacion<TGenotipo> mutacion = new PoliticaMutacionReglas2(generador, interpretacion, probMutacion);
        PoliticaSeleccion<TGenotipo> seleccion = new PoliticaSeleccionConstante<>(tamanoPoblacion);
        HandOfGod<TGenotipo> hog;

        ArrayList<TGenotipo> pop = new ArrayList<>();
        for (int i = 0; i < tamanoPoblacion; i++) {
            pop.add(generador.generar());
        }


        hog = new HandOfGod<>(f, pop, mezcla, mutacion, seleccion, tamanoElite);
        for (int i = 0; i < nEpocas; i++) {
            // System.out.println("Epoca: " + i + ", individuos: " + hog.poblacionActual().size());
            // System.out.println("Reglas max: " + hog.poblacionActual().get(0).l().size()
            //        + "=>" + hog.poblacionActual().get(0).r());
            hog.iterate();
            //System.out.println(hog.poblacionActual().get(0).l().size());
            //System.out.println(hog.poblacionActual().get(0).l());
            //System.out.println(hog.poblacionActual().get(0).r());
            /*System.out.println("AvgNRegla:");
            double sum = 0.0;
            for(Weighted<TGenotipo> t: hog.poblacionActual())
            {
            	sum+=t.l().size();
            }
            System.out.println(sum/hog.poblacionActual().size());
            System.out.println("***");*/
            //System.out.println("Poblacion:"+hog.poblacionActual().size());
        }

        reglaFinal = hog.poblacionActual().get(0).l();
        System.out.println(
                "El fitness de la regla final es " + f.f(reglaFinal));
        System.out.println(reglaFinal);
    }

    @Override
    protected void inicializarParametros(Map<String, Object> parametros) {
        probCruce = 0.3;
        decayCruce = 0.93;        
        propTest = 0.2;
        probMutacion = 0.1;
        tamanoPoblacion = 250;
        tamanoElite = 35;
        nReglasMedio = 10;
        nEpocas = 500;
        sizePenalty = 0;

        if (parametros.get("probCruce") != null) {
            probCruce = (Double) parametros.get("probCruce");
        }
        if (parametros.get("decayCruce") != null) {
            decayCruce = (Double) parametros.get("decayCruce");
        }
        if (parametros.get("propTest") != null) {
            propTest = (Double) parametros.get("propTest");
        }
        if (parametros.get("probMutacion") != null) {
            probMutacion = (Double) parametros.get("probMutacion");
        }
        if (parametros.get("tamanoElite") != null) {
        	tamanoElite = (Integer) parametros.get("tamanoElite");
        }
        if (parametros.get("tamanoPoblacion") != null) {
            tamanoPoblacion = (Integer) parametros.get("tamanoPoblacion");
        }
        if (parametros.get("nReglasMedio") != null) {
            nReglasMedio = (Double) parametros.get("nReglasMedio");
        }
        if (parametros.get("nEpocas") != null) {
            nEpocas = (Integer) parametros.get("nEpocas");
        } 
        if (parametros.get("sizePenalty") != null) {
            nEpocas = (Integer) parametros.get("sizePenalty");
        } 
    }
}
